#!/usr/bin/env python
# -*- coding: utf-8 -*-

from util import safestr, safeunicode


def get_formatter_by_name(name='BBCode'):
    return globals()[name + 'Formatter']


## ---- Base Formatter Class

class Formatter(object):
    pass


## ---- BBCode Formatter
'''
class BBCodeFormatter(Formatter):
    format_type = 'BBCode'

    def __init__(self):
        pass

    def bind_lexer(self, lexer):
        self.lexer = lexer

    def do_block_default(self, text):
        return '\n%s\n' % text.strip('\n')

    def do_inline(self, name, context):
        mapper = {
            'italic': 'i',
            'bold': 'b',
            #'highlight': 'highlight',
        }
        if name in mapper.keys():
            tag = mapper[name]
            return '[%s]%s[/%s]' % (tag, context[name], tag)
        else:
            f = getattr(self, '_%s_inline' % name, None)
            if f and callable(f):
                return f(context)
            return None


    def do_block(self, name, context):
        f = getattr(self, '_%s_block' % name, None)
        if f and callable(f):
            return f(context)
        else:
            return '#Action#continue'

    def do_hash(self, name, context):
        name = context.get('dynamic_name', name)
        f = getattr(self, '_%s_hash' % name, None)
        if f and callable(f):
            return f(context)
        else:
            return context['rawText']


  ## ---- Inline

    def _monospace_inline(self, context):
        w = context['monospace']
        return '[font=monospace][color=green][b]%s[/b][/color][/font]' % (w)

    def _highlight_inline(self, context):
        w = context['highlight']
        return '[color=red][b]%s[/b][/color]' % (w)


  ## ---- Block

    def _header_block(self, context):
        return None

    def _blockquote_block(self, context):
        return '\n[quote]\n%s\n[/quote]\n' % context['rawText'].replace('>>>', '  ', 1)

    def _list_block(self, context):
        out = ['[list]\n']
        for item in context['_list']:
            out.append('  [*]%s\n' % self.lexer.do_inline(item))
        out.append('[/list]')
        return ''.join(out)


  ## ---- Hash

    def _code_hash(self, context):
        from pygments import highlight
        from pygments.formatters import BBCodeFormatter
        from pygments.lexers import get_lexer_by_name, TextLexer

        text = safeunicode(context['content'])
        lang = context['_attr'].get('lang', 'NoLang')
        _use_code = True
        _use_mono = False

        if lang == 'OD':
            from synrender import ODLexer, ODDefaultStyle
            lexer = ODLexer()
            formatter = BBCodeFormatter(codetag=_use_code, monofont=_use_mono, encoding='utf-8', style=ODDefaultStyle)
        else:
            try:
                lexer = get_lexer_by_name(lang)
                formatter = BBCodeFormatter(codetag=_use_code, monofont=_use_mono, encoding='utf-8', style="vs") #native
            except ValueError:
                rst = "[font=monospace][color=#AA22FF]\n%s\n[/color][/font]" % safestr(text)
                if _use_code:
                    rst = "[code]%s[/code]" % rst
                return rst
        return highlight(text, lexer, formatter)


    def _link_hash(self, context):
        if context['type'] == 'url':
            return "[url=%s][color=blue][u]%s[/u][/color][/url]" % (context['link'], context['link'])
        elif context['type'] == 'img':
            return "[img]%s[/img]" % context['link']
        elif context['type'] == 'url_text':
            return "[url=%s][color=blue][u]%s[/u][/color][/url]" % (context['link'], context['repl'])
        elif context['type'] == 'url_img':
            return "[url=%s][img]%s[/img][/url]" % (context['link'], context['repl'])
'''

## ---- HTML Formatter

class HTMLFormatter(Formatter):
    format_type = 'HTML'

    def __init__(self):
        pass

    def bind_lexer(self, lexer):
        self.lexer = lexer

    def do_block_default(self, text):
        # Just a para.
        return '\n<p>%s</p>\n' % text.strip('\n')

    def do_inline(self, name, context):
        mapper = {
            'italic': 'i',
            'bold': 'b',
        }

        # Simple map or call a func.
        if name in mapper.keys():
            tag = mapper[name]
            return '<%s>%s</%s>' % (tag, context[name], tag)
        else:
            f = getattr(self, '_%s_inline' % name, None)
            if f and callable(f):
                return f(context)
            return None # We ignore it.


    def do_block(self, name, context):
        f = getattr(self, '_%s_block' % name, None)

        if f and callable(f):
            return f(context)
        else:
            # Let other block handle it.
            return '#Action#continue'

    def do_hash(self, name, context):
        name = context.get('dynamic_name', name)
        f = getattr(self, '_%s_hash' % name, None)

        # Hash it or ignore.
        if f and callable(f):
            return f(context)
        else:
            return context['rawText']


  ## ---- Inline

    def _monospace_inline(self, context):
        w = context['monospace']
        return '<span><code>%s</code></span>' % (w)

    def _highlight_inline(self, context):
        w = context['highlight']
        return '<span class="highlight"><code>%s</code></span>' % (w)


  ## ---- Block

    def _header_block(self, context):
        lvl = len(context['level'])
        return '\n<h%d>%s</h%d>\n' % ( lvl, context['body'], lvl)

    def _blockquote_block(self, context):
        return '\n<blockquote>\n%s\n</blockquote>\n' % context['rawText'].replace('>>>', '  ', 1)

    def _list_block(self, context):
        out = ['<ul>\n']
        for item in context['_list']:
            out.append('  <li>%s</li>\n' % self.lexer.do_inline(item))
        out.append('</ul>')
        return ''.join(out)

    def _table_block(self, context):
        out = ['<table>\n']
        out.append('  <tr>')
        for th in context['table_header']:
            out.append('<th>%s</th>' % th)
        out.append('  </tr>\n')
        for entry in context['table_body']:
            out.append('  <tr>')
            for tr in entry:
                out.append('<td>%s</td>' % th)
            out.append('  </tr>\n')
        out.append('</table>')
        return ''.join(out)


  ## ---- Hash

    def _code_hash(self, context):
        from pygments import highlight
        from pygments.formatters import HtmlFormatter
        from pygments.lexers import get_lexer_by_name, TextLexer

        text = safeunicode(context['content'])
        lang = context['_attr'].get('lang', 'NoLang')
        _use_code = True
        _use_mono = False

        try:
            lexer = get_lexer_by_name(lang)
            formatter = HtmlFormatter(noclasses=True, monofont=_use_mono, encoding='utf-8', style="vs")
        except ValueError:
            rst = '<div class="code"><pre>\n%s\n</pre></div>' % safestr(text)
            return rst

        return highlight(text, lexer, formatter)


    def _link_hash(self, context):
        if context['type'] == 'url':
            return '<a href="%s">%s</a>' % (context['link'], context['link'])
        elif context['type'] == 'img':
            return '<img src="%s" />' % context['link']
        elif context['type'] == 'url_text':
            return '<a href="%s">%s</a>' % (context['link'], context['repl'])
        elif context['type'] == 'url_img':
            return '<a href="%s"><img src="%s" /></a>' % (context['link'], context['repl'])

